import marshal
import types
import time
import MySQLdb
import pickle

class object_factory:

    db = None
    cursor = None
    dumpdata = ''
    keyval = {}


    def create_db(self, h,u, p, n):
        self.db = MySQLdb.connect(h,u,p,n)
        self.cursor = self.db.cursor()
        self.cursor.execute('use '+n)

    def get_db(self):
        return self.cursor
    
    def create_obj(self, user):
        o = obj()
    o.owner = user.id
        o.obj_created=time.ctime()
        o.obj_modified=time.ctime()
        o.set_acl(user.username,['r', 'w', 'x'], [user.id,], user)
    c = self.get_db()
    c.execute('select count(id) from obj')
    o.id = c.fetchone()[0]+1
    c.execute('insert into obj(obj_serial,modified,created) values("'+pickle.dumps(o)+'","'+time.ctime()+'", "'+time.ctime()+'")')
        return o        

#    def setattr(self, attr, val):
#        if self.keyval.has_key(attr):
#            return False
#        else:
#            self.keyval[attr] = val
#            return True

#    def getattr(self, attr):
#        if self.keyval.has_key(attr):
#            return self.keyval[attr]
#        else:
#            return None

    def get_all_obj(self):
        self.db.execute('select obj_serial from obj')
        return self.db.fetchall()

    def get_obj_by_owner(self, id):
        ab = self.get_all_obj()
        list=[]
        for x in ab:
            list.append(marshal.loads(x))
        list2 = []
        for y in list:
            print y.get_acl()

    def set_obj(self, l):
        ass = pickle.dumps(l)
        return self.cursor.execute('insert into obj(id, obj_serial, modified) values('+str(l.id)+', "'+ass+'","'+time.ctime()+'") on duplicate key update obj_serial="'+ass+'", modified="'+time.ctime()+'"')

    def get_obj(self, id):
        data = self.cursor.execute('select obj_serial from obj where id='+str(id))
        return pickle.loads(self.cursor.fetchone()[0])


class link_manager(object_factory):
    def create_link(self, url):
        l = link()
        l.url = url
        self.cursor.execute('select count(id) from link')
        cou = self.cursor.fetchone()
        l.id = cou[0]+1
        ass = pickle.dumps(l)
        self.cursor.execute('insert into link(id, obj_serial) values('+str(cou[0])+',"'+ass+'") on duplicate key update obj_serial="'+ass+'"')
        return l

    def set_link(self, l):
        ass = pickle.dumps(l)
        return self.cursor.execute('insert into link(id, obj_serial, modified) values('+str(l.id)+', "'+ass+'",'+str(time.time())+' on duplicate key update obj_serial="'+ass+'", modified='+time.ctime())
    def get_link(self, id):
        data = self.cursor.execute('select obj_serial from link where id='+str(id))
        return pickle.loads(self.cursor.fetchone())

class obj:
    id = 0
    obj_created = -1
    obj_modified = -1
    __parents = []
    __children = []
    __auth = {}
    __keyval = {}
    __methods = {}
    owner = None

    def get_owner(self):
        return self.owner

    def set_owner(self, o):
        self.owner = o.id

    def set_parents(self, data=[]):
        for x in data:
            self.parents.append(x)

    def get_parents(self):
        return self.parents

    def inherit(self, l):
        self.parents.append(l.id)
        l.set_children([l.id])

    def set_children(self, data = []):
        for x in data:
            self.children.append(x)

    def get_children(self):
        return self.children

    def set_acl(self, attr, ap,g, owner):
    if ap.index('r')<0 or ap.index('w')<0 or ap.index('x')<0:
        raise Exception('invalid acl')
    if owner.id != self.owner:
        raise Exception('owner of object required to set acl')
    elif owner.loggedin==False:
        raise Exception('no login')
    ac = acl()
        for x in g:
            if self.__auth.has_key(attr):
                self.__auth[attr].append(ac.set_ace(x, ap))
            else:
                self.__auth[attr] = []
                self.__auth[attr].append(ac.set_ace(x, ap))

    def get_acl(self,attr, owner):
## leaving get_acl without any security
## if someone wants to read who has access
## or wants access themself
## they can join a group of one of the objects
        return self.__auth[attr]

    def set_method(self, name, func, obj_id):
        ace = self.get_acl_by_id(name, obj_id)
        if ace.index('x')>0:
            self.__method[name] = func

    def get_method(self, name, obj_id):
        ace = self.get_acl_by_id(name, obj_id)
        if ace.index('x')>0:
            return self.__method[name]

    def set_attr(self, attr, val, obj_id):
    ace = self.get_acl_by_id(obj_id)
    if ace.index('w')>0:
            self.__keyval[attr] = val
    else:
        raise Exception('no write access')

    def get_attr(self,attr, obj_id):
    ace = self.get_acl_by_id(attr, obj_id)
    if ace.index('r')>0:
        return self.__keyval[attr]
    else:
        raise Exception('no read access')

    def get_acl_by_id(self, attr, id):
    ac = []
        for x in self.__auth[attr]:
        return x.get_ace(id)    

    def authenticate(self, username, attr, access):
        if username.loggedin:
            id = username.id
            acl = self.get_acl(attr)
            for x in self.__auth[acl]:
                if x==id:
                    if self.__auth[acl][x].contains(access):
                        return True
                    else: return False
        return False

class acl:
    __objects = {}
    
    def get_ace(self, objid):
        return __objects[objid]

    def set_ace(self, objid, permissions=[]):
        self.__objects[objid] = permissions

    #def __setattr__(self, attr, val):
        

#class obj:
#    id = 0
#    obj_created = ''
#    obj_modified = ''
#    parents = []
#    children = []

class group_manager(object_factory):
    
    def create_group(self, n, cr, lis):
        a = group()
        a.group_name = n
        a.group_creator = cr
        a.group_list.append(lis)
        #ass = pickle.dumps(a)
        self.db.execute('select count(id) from dog2dog_corevet.group')
        ab = self.db.fetchone()[0]+1
        a.id = ab
        ass = pickle.dumps(a)
        print ass, ab, a, str(time.time())
        self.db.execute('insert into dog2dog_corevet.group(id, obj_serial, created, modified) values('+str(ab)+', "'+ass+'","'+time.ctime()+'","'+time.ctime()+'")')
        return a

    def set_group(self, g):
        ass = pickle.dumps(g)
        return self.db.execute('insert into dog2dog_corevet.group(id, obj_serial, modified) values('+str(g.id)+', "'+ass+'", "'+time.ctime()+'") on duplicate key update obj_serial="'+ass+'", modified="'+time.ctime()+'"')

    def get_group(self,id):
        self.db.execute('select obj_serial from dog2dog_corevet.group where id='+str(id))
        ab = pickle.loads(self.db.fetchone()[0])
        return ab

class group(obj):
    group_id=0
    group_name = ''
    group_creator = 0
    group_list = [0,]

    def add_member(self, id):
        self.group_list[1].append(id)

    def get_members(self):
        return self.group_list[1]


class user_manager(object_factory):

    def create_user(self, u, p, e):
        a = user()
        a.username = u
        a.password = p
        a.email = e
        self.db.execute('select count(id) from dog2dog_corevet.user')
        c = self.db.fetchone()[0]+1
        a.id = c
        ass = pickle.dumps(a)
        self.db.execute('insert into dog2dog_corevet.user(id, obj_serial,created, modified) values('+str(c)+', "'+ass+'", "'+time.ctime()+'","'+time.ctime()+'")')
        return a

    def get_user(self, id, u, p):
        self.db.execute('select obj_serial from dog2dog_corevet.user where id='+str(id))    
        obj = pickle.loads(self.db.fetchone()[0])
        if obj.login(u, p):
            return obj
        else:
            return None

    def set_user(self, obj):
        ass = pickle.dumps(obj)
        ss = 'insert into dog2dog_corevet.user(id, obj_serial, modified) values ('+str(obj.id)+', "'+ass+'", "'+time.ctime()+'") on duplicate key update obj_serial="'+ass+'", modified="'+time.ctime()+'"'
        return self.db.execute(ss)

    def get_all_users(self):
        ss = 'select * from user'
        self.db.execute(ss)
        a = self.db.fetchall()
        r = []
        #return a
        for y in a:
            r2 = []
            r2.append(y[0])
            r2.append(pickle.loads(y[1]))
            r2.append(y[2])
            r2.append(y[3])
            r.append(r2)
        return r

    def get_users(self, dd):
        a = []
        for x in dd:
            ss = 'select obj_serial from user where id='+str(x)
            self.db.execute(ss)
            one = self.db.fetchone()[0]
            print one
            a.append(pickle.loads(one))

        return a

class user(obj):
    username = 'guest'
    password = 'obsequious'
    email = 'admin@****.com'
    loggedin = False
    contact = 'xxx-xxx-xxxx'
    home = 'xxx-xxx-xxxx'
    work = 'xxx-xxx-xxxx'
    cel = 'xxx-xxx-xxxx'
    address = 'xxxx @@@@ Street'
    city = 'Fairlane'
    state = 'md'
    zip = 'xxxxx-xxxx'

    def login(self, u, p):
        if u==self.username and p== self.password:
            self.loggedin = True
            return True
        else:
            return False

    

class file_manager(object_factory):
    
    def create_fileobj(self, l, n, owner):
        a = file()
        a.file_loc=l
        a.file_name=n
        a.owner=owner
        self.db.execute('select count(id) from file')
        c = self.db.fetchone()[0]+1
        a.id = c
        ass = pickle.dumps(a)
        self.db.execute('insert into file(id, obj_serial, created, modified) values('+str(a.id)+', "'+ass+'", "'+time.ctime()+'","'+time.ctime()+'"')
        return a

class folder_manager(object_factory):

    def create_folderobj(self, l, n, crea):    
        a = folder()
        a.fol_loc=l
        a.fol_name =n
        a.fol_list = [-1]
        a.owner = crea
        self.db.execute('select count(id) from folder')
        c = self.db.fetchone()[0]+1
        a.id = c
        ass = pickle.dumps(a)
        self.db.execute('insert into folder(id, obj_serial, created, modified) values('+str(a.id)+', "'+ass+'", "'+time.ctime()+'","'+time.ctime()+'"')
        return a

class folder(obj):
    fol_loc = '\home\dog2dog\\'
    fol_name = 'fol1'
    fol_list = [-1,]
    owner = -1

class file(obj):
    file_loc = '\home\dog2dog2\\'
    file_name = 'dump.txt'
    owner = -1


class link(obj):
    url = 'http://www.google.com'

class event(obj):
    exec_time = -1
    func_name = '__name__'
    func_code = '__code__'
    sudo = True

class event_manager(object_factory):

    def create_event(self, exec1, name, code, sudo):
        a = event()
        a.exec_time = exec1
        a.func_name = name
        a.func_code = code
        a.sudo = sudo
        return a

    def get_events(self):
        self.db.execute('select obj_serial from event')
        b = self.db.fetchall()
        return b
    

class authenticator(object_factory):

    def create_ace(self, grant=[], deny=[]):
        ace = {'grant': grant, 'deny': deny}

